/**
  * @authors	Cameron Stewart, Tyler Williams, Fatimah Alowa, 
  *		Marlon Boothe,    Lauren Walker
  * @version	Group 2 Project 3 part 2
  * @since	2012-10-24
  */

#include <sstream>
#include <iostream>
#include "Scanner.h"

/**
	*Constructor for Scanner class, initializes charTable values
	*
	*@param const string $str
	*/
Scanner::Scanner(const string &str){
    for(int i=0; i<=127; i++){
        if((i>=65 && i<=90) || (i>=97 && i<=122)){
            charTable[i]=LETTER;
        }else if(i>=48 && i<=57){
            charTable[i]=DIGIT;
        }else if(i==39 || i==96){
            charTable[i]=QUOTE;
        }else if(i==127){
            charTable[i]=EOF_CODE;
        }else{
            charTable[i]=SPECIAL;
        }
    }
    sourceFile=fopen(str.c_str(),"r+");
    printer=new Print(str);
}
Scanner::~Scanner(){
	//destructor
}

/**
	*Scans and prints the tokens until '.'
	*
  *@param &tok  address to Tokenizer object 
	*
	*@return void
	*/
   
void Scanner::ScanFile(Tokenizer &tok){ 
    lineCount=0;
    while(tok.GetTokenCode()!=PERIOD){
        tok.GetToken(charTable);
        printer->PrintToken(tok);
    }
}

/**
	*checks the current state of the sourceLine and gets
	*a new sourceLine if it is at the edn of a line
	*If it sees a Pascal Comment it skips the comment
	*(a pascal comment is anything between '{' and '}')
	*
	*@return char
	*/
   
char Scanner::GetCharacter(){
  
    if(sourceLineIndex>=sourceLine.length()){
        GetSourceLine();
        lineCount++;
        sourceLineIndex=0;
        string str = static_cast<ostringstream*>( &(ostringstream() << lineCount) )->str();
        printer->PrintLine(str+": "+sourceLine);

    }
    if(sourceLine[sourceLineIndex]=='{'){
        SkipComment();
    }
    sourceLineIndex++;
    return sourceLine[sourceLineIndex-1];
}

/** 
	* backs up the sourceLineIndex, in case the Tokenizer has
	*viewed a character and it wasnts to go back to view it later.
	*
	*@return void
	*/
   
void Scanner::BackUpCharacter(){

    sourceLineIndex--;
}

/** 
	*Gets the next source line from the file and returns true.
	*If there is not a next sourceLine in file/source_buffer will return false
	*/
     
bool Scanner::GetSourceLine(){
    char source_buffer[MAX_SOURCE_LINE_LENGTH]={'\0'};
    
	if(fgets(source_buffer, sizeof source_buffer, sourceFile)!='\0'){
        sourceLineIndex=0;
        sourceLine=source_buffer;
		return true;
	}else{
		return false;
	}
}

/**
	*Skips "comment" or anything between '{' and '}'
	*by increasing the sourceLineIndex until the '}' is reached
	*
	*@return void
	*/
     
void Scanner::SkipComment(){
    while(sourceLine[sourceLineIndex]!='}'){
        sourceLineIndex++;
    }
    sourceLineIndex++;
}